package com.zt.questionnaire.common.config.redis;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.questionnaire.common.utils.SpringContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.lang.reflect.Method;

@ConfigurationProperties(prefix = "redis")
@Slf4j
//@PropertySource("classpath:application.properties")
@EnableCaching
@Data
public class RedisConfig extends RedisConfigurerSupport {

    private String host;
    private String password;
    private int port;
    private int timeout = 3600;
    private int max_idle = 100;
    private long max_wait_millis = 1;

    @Autowired
    SpringContext context;


    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setTimeout((int) timeout);
        if (password != null) {
            factory.setPassword(password);
        }

        return factory;
    }

    @Bean
    public JedisPool redisPoolFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(max_idle);
        jedisPoolConfig.setMaxWaitMillis(max_wait_millis);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        return jedisPool;
    }

    /**
     * @return 自定义策略生成的key
     * @description 自定义的缓存key的生成策略
     * 若想使用这个key  只需要讲注解上keyGenerator的值设置为keyGenerator即可</br>
     */
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }


    //缓存管理器
    @Bean
    public RedisCacheManager cacheManager(JedisConnectionFactory jedisConnectionFactory) {
        return RedisCacheManager.create(jedisConnectionFactory);
    }

    /**
     * RedisTemplate配置
     *
     * @param jedisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
        //设置序列化
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //配置redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);//key序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//value序列化
        redisTemplate.setHashKeySerializer(stringSerializer);//Hash key序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//Hash value序列化
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public CacheOperator redisOperator(RedisTemplate redisTemplate) {
        CacheOperator operator = new CacheOperator();
        operator.redisTemplate = redisTemplate;
        operator.context = context;
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
//		operator.setInt("aaa", 1);
//		operator.remove("aaa");
        return operator;
    }

    /**
     * redis消息队列监听信息（订阅消息），如果需要定义消息，获取RedisMessageListenerContainer的实例container，
     * 通过container.addMessageListener(a, new PatternTopic(channel_account_register));添加定义消息
     *
     * @param connectionFactory
     * @param listenerAdapter
     * @return
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
//		//订阅login_pub频道上的消息
//		container.addMessageListener(a, new PatternTopic(channel_account_register));
//		container.addMessageListener(b, new PatternTopic(channel_account_login));
        return container;
    }

//    /**
//     * RedisTemplate配置
//     *
//     * @param jedisConnectionFactory
//     * @return
//     */
//    @Bean
//    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory ) {
////        //设置序列化
////        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
////        ObjectMapper om = new ObjectMapper();
////        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
////        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
////        jackson2JsonRedisSerializer.setObjectMapper(om);
//        //配置redisTemplate
//        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
//        redisTemplate.setConnectionFactory(jedisConnectionFactory);
//        RedisSerializer stringSerializer = new StringRedisSerializer();
//        //redis的键直接指定字符串格式
//        redisTemplate.setKeySerializer(stringSerializer);//key序列化
////        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//value序列化
//        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer ());//value序列化
//      //hash的key和value的序列化针对的是hashMap数据结构，key和value都用json的序列化，key不用字符串，否则调用
//		//的时候必须显示的转成字符串，特别是集合存放的时候，需要遍历转换，不方便
//        redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer ());//Hash key序列化
////        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//Hash value序列化
//        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer ());//Hash value序列化
//        redisTemplate.afterPropertiesSet();
//        return redisTemplate;
//    }
//
//
//	@Bean
//	public RedisUtils redisOperator(RedisTemplate<String, Object> redisTemplate) {
//		RedisUtils operator = new RedisUtils();
//		operator.redisTemplate = redisTemplate;
//		operator.context = context;
////		HashOperations<String,String,String> hashOperations = redisTemplate.opsForHash();
////		operator.setInt("aaa", 1);
////		operator.remove("aaa");
//		return operator;
//	}
//
//	/**
//	 * redis消息队列监听信息（订阅消息），如果需要定义消息，获取RedisMessageListenerContainer的实例container，
//	 * 通过container.addMessageListener(a, new PatternTopic(channel_account_register));添加定义消息
//	 *
//	 * @param connectionFactory
//	 * @param listenerAdapter
//	 * @return
//	 */
//	@Bean
//	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
//		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
//		container.setConnectionFactory(connectionFactory);
////		//订阅login_pub频道上的消息
////		container.addMessageListener(a, new PatternTopic(channel_account_register));
////		container.addMessageListener(b, new PatternTopic(channel_account_login));
//		return container;
//	}
}
